'use strict';

/**
 * 在JavaScript中，用var申明的变量实际上是有作用域的。

 如果一个变量在函数体内部申明，则该变量的作用域为整个函数体，在函数体外不可引用该变量：
 */
function foo() {
    var x = 1;
    x = x + 1;
    console.log(x);
}

// x = x + 2; //
// ReferenceError! 无法在函数体外引用变量x
// 如果两个不同的函数各自申明了同一个变量，那么该变量只在各自的函数体内起作用。换句话说，不同函数内部的同名变量互相独立，互不影响：
function bar() {
    var x = 'A';
    x = x + 'B';
    console.log(x);
}

// 由于JavaScript的函数可以嵌套，此时，内部函数可以访问外部函数定义的变量，反过来则不行：
function func1() {
    const x = 1;

    function bar() {
        const x = 'A';
        console.log('x in bar() = ' + x); // 'A'
    }

    console.log('x in foo() = ' + x); // 1
    // 调用内部函数
    bar();
}

// JavaScript的函数定义有个特点，它会先扫描整个函数体的语句，把所有申明的变量“提升”到函数顶部：
function func2() {
    var x = 'Hello, ' + y;
    console.log(x);
    var y = 'Bob';
    // 虽然是strict模式，但语句var x = 'Hello, ' + y;并不报错，原因是变量y在稍后申明了。但是console.log显示Hello, undefined，说明变量y的值为undefined。这正是因为JavaScript引擎自动提升了变量y的声明，但不会提升变量y的赋值。
}

// 对于上述func2()函数，JavaScript引擎看到的代码相当于：
function func3() {
    let y; // 提升变量y的申明，此时y为undefined
    const x = 'Hello, ' + y;
    console.log(x);
    y = 'Bob';
    console.log(x);

}